﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

using AcctrueWMS.Foundation.Common.Exception;
namespace AcctrueWMS.Foundation.Data
{
    public class CommandExprFactory
    {
        static Dictionary<CommandExpressionTypeEnum, IExpressionEvaler> exprEvalers = new Dictionary<CommandExpressionTypeEnum, IExpressionEvaler>();
        static Dictionary<Regex,CommandExpressionTypeEnum> exprPrefixes=new Dictionary<Regex,CommandExpressionTypeEnum>();
        static CommandExprFactory()
        {
            exprEvalers.Add(CommandExpressionTypeEnum.Array,new ArrayExpressionEvaler());
            exprEvalers.Add(CommandExpressionTypeEnum.WMSQL, new WMSQLExpressionEvaler());
            exprEvalers.Add(CommandExpressionTypeEnum.Sys, new SysExpressionEvaler());
            exprEvalers.Add(CommandExpressionTypeEnum.RealSQL, new SysExpressionEvaler());
            exprEvalers.Add(CommandExpressionTypeEnum.Text, new TextExpressionEvaler());

            exprPrefixes.Add(new Regex(@"sys\((.*)\)", RegexOptions.Singleline), CommandExpressionTypeEnum.Sys);
            exprPrefixes.Add(new Regex(@"array\((.*)\)", RegexOptions.Singleline), CommandExpressionTypeEnum.Array);
            exprPrefixes.Add(new Regex(@"wmsql\((.*)\)",RegexOptions.Singleline), CommandExpressionTypeEnum.WMSQL);
            exprPrefixes.Add(new Regex(@"realsql\((.*)\)", RegexOptions.Singleline), CommandExpressionTypeEnum.RealSQL);

        }
        /// <summary>
        /// 根据文本获取命令类型
        /// </summary>
        /// <param name="expression">表达式</param>
        /// <param name="cmdText">返回的实际执行的命令</param>
        /// <returns>命令类型</returns>
        public static CommandExpressionTypeEnum DetectType(string expression,out string cmdText)
        {
            cmdText = string.Empty;
            foreach (Regex regex in exprPrefixes.Keys)
            {
                if(regex.IsMatch(expression))
                {
                    cmdText = regex.Match(expression).Groups[1].Value;
                    return exprPrefixes[regex];
                }
            }
            cmdText = expression;
            return CommandExpressionTypeEnum.Text;

        }
        /// <summary>
        /// 执行命令表达式，返回数据结果
        /// </summary>
        /// <param name="expression">命令表达式</param>
        /// <returns>数据结果，不同命令返回内容不同</returns>
        public static object Eval(string expression,IDataModelContext context)
        {
            string cmdText;
            CommandExpressionTypeEnum type = DetectType(expression,out cmdText);
            IExpressionEvaler evaler=CreateEvaler(type);
            evaler.Context = context;
            return evaler.Eval(cmdText);
        }
        /// <summary>
        /// 将表达式中含有命令语句替换为值
        /// </summary>
        /// <param name="expr"></param>
        /// <returns></returns>
        public static string ReplaceWithEvaled(string expr,IDataModelContext context)
        {
            StringBuilder sb = new StringBuilder();
            int index = 0;
            foreach (Regex regex in exprPrefixes.Keys)
            {
                if (regex.IsMatch(expr))
                {
                    foreach (Match m in regex.Matches(expr))
                    {
                        sb.Append(expr.Substring(0, m.Index));
                        object obj = Eval(m.Groups[1].Value, context);
                        if (obj is string)
                            sb.Append(obj.ToString());
                        index += m.Index + m.Length;
                    }
                    sb.Append(expr.Substring(index, expr.Length - index));
                    expr = sb.ToString();
                    sb.Clear(); index = 0;
                }
            }
            return expr;
        }
        /// <summary>
        /// 根据命令类型获得不同的处理实例
        /// </summary>
        /// <param name="exprType">命令类型</param>
        /// <returns>处理实例</returns>
        public static IExpressionEvaler CreateEvaler(CommandExpressionTypeEnum exprType)
        {
            return exprEvalers[exprType];
        }
    }
}
